package com.yc.thread.wait.cp;

import java.util.LinkedList;

/**
 * 生产者和消费者的问题 wait、notify/notifyAll() 实现
 */
public class Storage1 implements AbstractStorage {
	//仓库最大容量
	private final int MAX_SIZE = 100;
	//仓库存储的载体
	private LinkedList list = new LinkedList();

	//生产产品
	public void produce(int num) {
		//同步
		synchronized (list) {
			//仓库剩余的容量不足以存放即将要生产的数量，暂停生产
			while (list.size() + num > MAX_SIZE) {//while替代if，直到条件满足，条件不满足就结束
				System.out.println("【要生产的产品数量】:" + num + "\t【库存量】:" + list.size() + "\t暂时不能执行生产任务!");

				try {
					//条件不满足，生产阻塞
					list.wait();//不sleep一下，不会死循环？
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
			//此时虽然已经没有“锁的保护”，但因为另一个线程只会消费，而不会新增，所以不用担心会超
			for (int i = 0; i < num; i++) {
				list.add(new Object());
			}

			System.out.println("【已经生产产品数】:" + num + "\t【现仓储量为】:" + list.size());
			//自己wait，自己notify。。。嗯，这里的锁和解锁（wait）是一个“全局”概念，所以谁操作都一样
			list.notifyAll();
		}
	}

	//消费产品
	public void consume(int num) {
		synchronized (list) {

			//不满足消费条件
			while (num > list.size()) {
				System.out.println("【要消费的产品数量】:" + num + "\t【库存量】:" + list.size() + "\t暂时不能执行生产任务!");

				try {
					list.wait();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}

			//消费条件满足，开始消费
			for (int i = 0; i < num; i++) {
				list.remove();
			}

			System.out.println("【已经消费产品数】:" + num + "\t【现仓储量为】:" + list.size());

			list.notifyAll();
		}
	}
}